﻿using System;
using System.Data;
using System.Data.Common;
using EntlibData = Microsoft.Practices.EnterpriseLibrary.Data;

namespace jcs.Core.Data
{
    public static class DataProvider
    {

        private const string CommandTypeNotImplemented = "The selected command type is not implemented.";
        private const int CommandTimeout = 300;

        public enum EntlibDataCommandType 
        {
            SqlString = 0,
            StoredProc
        }

        private static EntlibData.Database GetDatabase(string databaseName)
        {
            EntlibData.Database db = null;
            if (databaseName == String.Empty || databaseName == "Default")
            {
                db = EntlibData.DatabaseFactory.CreateDatabase();
            }
            else
            {
                db = EntlibData.DatabaseFactory.CreateDatabase(databaseName);
            }
            return db;
        }

        /// <summary>
        /// Really really REALLY destroys a IDataReader object.
        /// </summary>
        /// <remarks></remarks>
        public static void SwatFlyWithBuick(ref IDataReader rdr)
        {
            if (rdr == null) return;
            if (rdr.IsClosed == false)
            {
                rdr.Close();
            }
            rdr.Dispose();
            rdr = null;
        }

        /// <summary>
        /// Really really REALLY destroys a command object.
        /// </summary>
        /// <param name="cmd"></param>
        /// <remarks></remarks>
        public static void SwatFlyWithBuick(ref DbCommand cmd)
        {
            if (cmd == null) return;
            if (cmd.Connection != null && cmd.Connection.State != ConnectionState.Closed)
            {
                cmd.Connection.Close();
            }
            cmd = null;
        }

        public static DbCommand GetCommand(string databaseName, string commandText, EntlibDataCommandType commandType, bool autoDiscoverParameters)
        {
    
            DbCommand cmd = null;
            var db = GetDatabase(databaseName);
            if (db == null) return null; 
            switch (commandType) {
                case EntlibDataCommandType.SqlString:
                    cmd = db.GetSqlStringCommand(commandText);
                    break;
                case EntlibDataCommandType.StoredProc:
                    cmd = db.GetStoredProcCommand(commandText);
                    if (autoDiscoverParameters == true) db.DiscoverParameters(cmd); 
                    //discovers the parameters for the stored proc
                    break;
                default:
                    throw new NotImplementedException(CommandTypeNotImplemented);
            }

            cmd.Connection = db.CreateConnection();
            cmd.CommandTimeout = CommandTimeout;
            return cmd;
        }


        /// <summary>
        /// Retrurns a loaded datareader object.
        /// </summary>
        /// <param name="storedProcName"></param>
        /// <param name="paramValues"></param>
        /// <returns></returns>
        public static IDataReader GetDataReader(string storedProcName, params object[] paramValues)
        {
            IDataReader Rdr = null;
            var Database = EntlibData.DatabaseFactory.CreateDatabase();
            if (Database != null)
            {
                DbCommand Cmd = Database.GetStoredProcCommand(storedProcName, paramValues);
                Rdr = Database.ExecuteReader(Cmd);
            }
            return Rdr;
        }

        public static IDataReader GetDataReader(string sql)
        {

            IDataReader Rdr = null;
            var Database = EntlibData.DatabaseFactory.CreateDatabase();
            if (Database != null)
            {
                DbCommand Cmd = Database.GetSqlStringCommand(sql);
                Rdr = Database.ExecuteReader(Cmd);
            }
            return Rdr;
        }

        /// <summary>
        /// Returns a loaded datatable object.
        /// </summary>
        /// <param name="commandText"></param>
        /// <param name="paramValues"></param>
        /// <returns></returns>
        public static DataTable GetDataTable(string commandText, params object[] paramValues)
        {
            DataTable Dt = null;
            var Database = EntlibData.DatabaseFactory.CreateDatabase();
            if (Database != null)
            {
                var Cmd = Database.GetStoredProcCommand(commandText, paramValues);
                var Ds = Database.ExecuteDataSet(Cmd);
                if (Ds != null && Ds.Tables.Count > 0)
                {
                    Dt = Ds.Tables[0];
                }
            }
            return Dt;
        }

        public static T GetReaderItem<T>(IDataReader reader, string name, T defaultValue)
        {
            T retVal = defaultValue;
            object dbValue = null;
            if (reader != null)
            {
                dbValue = reader[name];
                if (dbValue != System.DBNull.Value)
                {
                    retVal = (T)dbValue;
                }
            }
            return retVal;
        }

        public static T GetReaderItem<T>(IDataReader reader, int index, T defaultValue)
        {
            T retVal = defaultValue;
            object dbValue = null;
            if (reader != null)
            {
                dbValue = reader[index];
                if (dbValue != System.DBNull.Value)
                {
                    retVal = (T)dbValue;
                }
            }
            return retVal;
        }


    }
}
